package utils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"io"
	"math/rand"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// Str 字符处理类
type strext struct{}

// CurrTime 当前时间处理
func Str() *strext {
	return &strext{}
}

/*
生成随机数
*/
func (s *strext) RandInt(min, max int64) int64 {
	if min >= max || min == 0 || max == 0 {
		return max
	}

	rand.Seed(time.Now().Unix())
	return rand.Int63n(max-min) + min
}

/*
生成随机数
*/
func (s *strext) RandString(min, max int64) string {
	v := s.RandInt(min, max)

	return strconv.FormatInt(v, 10)
}

// Time 获取当前时间 time.Time 类型
func (s *strext) MD5(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	h.Write([]byte("lyc7751"))
	return hex.EncodeToString(h.Sum(nil))
}

// FileMd5获取文件的md5
func (s *strext) FileMd5(pathurl string) string {
	h := md5.New()
	f, err := os.Open(pathurl)
	if err != nil {
		return ""
	}
	io.Copy(h, f)
	return hex.EncodeToString(h.Sum(nil))
}

// 强制转换为int类型数据
// 如果转换失败则返回0
func (b *strext) TryUInt(val string) uint {
	return uint(b.TryInt64(val))
}

// 强制转换为int64数据
func (b *strext) TryUInt64(value string) uint64 {
	return uint64(b.TryInt64(value))
}

// 强制转换为int类型数据
// 如果转换失败则返回0
func (b *strext) TryInt(val string) int {
	return int(b.TryInt64(val))
}

// 强制转换为字符串
// 并清除前后空格
func (b *strext) TryStr(value interface{}) string {
	if val, ok := value.([]byte); ok {
		return strings.TrimSpace(string(val))
	} else if val, ok := value.(string); ok {
		return strings.TrimSpace(val)
	}
	return ""
}

// 强制转换为int64数据
func (b *strext) TryInt64(value interface{}) int64 {
	if val, ok := value.([]byte); ok {
		v, _ := strconv.ParseInt(string(val), 10, 64)
		return v
	} else if val, ok := value.(string); ok {
		v, _ := strconv.ParseInt(val, 10, 64)
		return v
	} else if val, ok := value.(int64); ok {
		return val
	} else if val, ok := value.(int); ok {
		return int64(val)
	}
	return 0
}

// getAesKey 获取aes加解密Key
func (b *strext) getAesKey() []byte {
	return []byte("lyc7751vlyc7751v")
}
func (b *strext) pkcs5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
func (b *strext) pkcs5UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

// AesEncrypt 加密，并返回base64后的字符串
func (b *strext) AesEncrypt(str string) (string, error) {
	if len(str) == 0 {
		return "", nil
	}

	origData := []byte(str)

	key := b.getAesKey()
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	blockSize := block.BlockSize()
	origData = b.pkcs5Padding(origData, blockSize)
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	crypted := make([]byte, len(origData))
	blockMode.CryptBlocks(crypted, origData)
	return base64.StdEncoding.EncodeToString(crypted), nil
}

// AesDecrypt 解密，传来base64的字符串
func (b *strext) AesDecrypt(str string) (string, error) {
	if len(str) == 0 {
		return "", nil
	}

	crypted, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		return "", err
	}

	key := b.getAesKey()
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	origData := make([]byte, len(crypted))
	blockMode.CryptBlocks(origData, crypted)
	origData = b.pkcs5UnPadding(origData)
	return string(origData), nil
}

// GetNewPassword 生成新密码
func (b *strext) GetNewPassword(lens int) string {
	advancestr := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+=-!@#"

	var passwd []byte = make([]byte, lens)
	for i := 0; i < lens; i++ {
		index := rand.Intn(len(advancestr))
		passwd[i] = advancestr[index]
	}
	return string(passwd)
}

func (b *strext) TrimHtml(src string) string {
	//将HTML标签全转换成小写
	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllStringFunc(src, strings.ToLower)
	//去除STYLE
	re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
	src = re.ReplaceAllString(src, "")
	//去除SCRIPT
	re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
	src = re.ReplaceAllString(src, "")
	//去除所有尖括号内的HTML代码，并换成换行符
	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
	src = re.ReplaceAllString(src, "")
	//去除连续的换行符
	re, _ = regexp.Compile("\\s{2,}")
	src = re.ReplaceAllString(src, "")
	return strings.TrimSpace(src)
}

func (b *strext) SubLenTrimHtml(str string, lens int) string {
	str = b.TrimHtml(str)
	return b.SubLen(str, lens)
}

func (b *strext) SubLen(str string, lens int) string {
	rs := []rune(str)
	if len(rs) == 0 {
		return ""
	}

	if lens > len(rs) {
		return str
	}

	return string(rs[0:lens])
}

func (b *strext) MaskPhoneNumber(phone string) string {
	if len(phone) != 11 {
		return phone
	}
	return phone[:3] + "****" + phone[7:]
}
func (b *strext) MaskEmail(email string) string {
	parts := strings.Split(email, "@")
	if len(parts) != 2 {
		return email
	}
	username := parts[0]
	domain := parts[1]

	length := len(username)
	if length <= 3 {
		return strings.Repeat("*", length) + "@" + domain
	}

	firstPart := username[:2]
	lastPart := username[length-1:]
	maskedUsername := firstPart + strings.Repeat("*", length-3) + lastPart
	return maskedUsername + "@" + domain
}
